package casper.alpha.utils;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class CasperProfiler {
        
        private static int p;
        private static boolean pub, improve, bounding;
        private static List<Double> times, counts;
        
        public static void setExperimentConfig(int inp, boolean inpub, boolean inimprove, boolean inbounding) {
                p = inp;
                pub = inpub;
                improve = inimprove;
                bounding = inbounding;
        }
        
        public static void standardDeviation() {
                if (n == 0 || n == 1) {
                        System.out.println("Cannot calculate SD due to n = " + n);
                        return;
                }
                double totalTime = 0;
                double totalCount = 0;
                for(Double d : times) {
                        totalTime += d;
                }
                for(Double d : counts) {
                        totalCount += d;
                }
                double meanTime = totalTime / n;
                double meanCount = totalCount / n;
                double ssdt = 0;
                double ssdc = 0;
                for(Double d : times) {
                        ssdt += (d - meanTime) * (d - meanTime);
                }
                for(Double d : counts) {
                        ssdc += (d - meanCount) * (d - meanCount);
                }
                ssdt = ssdt / (n-1);
                ssdc = ssdc / (n-1);
                ssdt = Math.sqrt(ssdt);
                ssdc = Math.sqrt(ssdc);
                System.out.println("SD Time = " + ssdt);
                System.out.println("SD Count = " + ssdc);
        }
        
        private static double atotalTime;
        private static double areduceTime;
        private static double aqueryTime;
        private static double afilterTime;
        private static int aobjectCount;

        private static double xtotalTime;
        private static double xreduceTime;
        private static double xqueryTime;
        private static double xfilterTime;
        private static int xobjectCount;

        private static double stotalTime;
        private static double sreduceTime;
        private static double squeryTime;
        private static double sfilterTime;
        private static int sobjectCount;

        private static int n;

        public static void clear() {
                atotalTime = 0;
                areduceTime = 0;
                aqueryTime = 0;
                afilterTime = 0;
                aobjectCount = 0;

                xtotalTime = 0;
                xreduceTime = 0;
                xqueryTime = 0;
                xfilterTime = 0;
                xobjectCount = 0;

                stotalTime = 0;
                sreduceTime = 0;
                squeryTime = 0;
                sfilterTime = 0;
                sobjectCount = 0;

                n = 0;
                
                times = new ArrayList<Double>();
                counts = new ArrayList<Double>();
        }

        public static double getAtotalTime() {
                return atotalTime;
        }

        public static void setAtotalTime(double atotalTime) {
                n++;
                CasperProfiler.atotalTime += atotalTime;
                CasperProfiler.setXtotalTime(atotalTime);
                CasperProfiler.setStotalTime(atotalTime);
                times.add(atotalTime);
        }

        public static double getAreduceTime() {
                return areduceTime;
        }

        public static void setAreduceTime(double areduceTime) {
                CasperProfiler.areduceTime += areduceTime;
                CasperProfiler.setXreduceTime(areduceTime);
                CasperProfiler.setSreduceTime(areduceTime);
        }

        public static double getAqueryTime() {
                return aqueryTime;
        }

        public static void setAqueryTime(double aqueryTime) {
                CasperProfiler.aqueryTime += aqueryTime;
                CasperProfiler.setXqueryTime(aqueryTime);
                CasperProfiler.setSqueryTime(aqueryTime);
        }

        public static double getAfilterTime() {
                return afilterTime;
        }

        public static void setAfilterTime(double afilterTime) {
                CasperProfiler.afilterTime += afilterTime;
                CasperProfiler.setXfilterTime(afilterTime);
                CasperProfiler.setSfilterTime(afilterTime);
        }

        public static int getAobjectCount() {
                return aobjectCount;
        }

        public static void setAobjectCount(int aobjectCount) {
                CasperProfiler.aobjectCount += aobjectCount;
                CasperProfiler.setXobjectCount(aobjectCount);
                CasperProfiler.setSobjectCount(aobjectCount);
                counts.add((double) aobjectCount);
        }

        public static double getXtotalTime() {
                return xtotalTime;
        }

        public static void setXtotalTime(double xtotalTime) {
                if (CasperProfiler.xtotalTime == 0
                                || xtotalTime > CasperProfiler.xtotalTime) {
                        CasperProfiler.xtotalTime = xtotalTime;
                }
        }

        public static double getXreduceTime() {
                return xreduceTime;
        }

        public static void setXreduceTime(double xreduceTime) {
                if (CasperProfiler.xreduceTime == 0
                                || xreduceTime > CasperProfiler.xreduceTime) {
                        CasperProfiler.xreduceTime = xreduceTime;
                }
        }

        public static double getXqueryTime() {
                return xqueryTime;
        }

        public static void setXqueryTime(double xqueryTime) {
                if (CasperProfiler.xqueryTime == 0
                                || xqueryTime > CasperProfiler.xqueryTime) {
                        CasperProfiler.xqueryTime = xqueryTime;
                }
        }

        public static double getXfilterTime() {
                return xfilterTime;
        }

        public static void setXfilterTime(double xfilterTime) {
                if (CasperProfiler.xfilterTime == 0
                                || xfilterTime > CasperProfiler.xfilterTime) {
                        CasperProfiler.xfilterTime = xfilterTime;
                }
        }

        public static int getXobjectCount() {
                return xobjectCount;
        }
        
        public static int getXobjectCount2() {
                return xobjectCount*2;
        }
        
        public static int getXobjectCount3() {
                return xobjectCount*3;
        }

        public static void setXobjectCount(int xobjectCount) {
                if (CasperProfiler.xobjectCount == 0
                                || xobjectCount > CasperProfiler.xobjectCount) {
                        CasperProfiler.xobjectCount = xobjectCount;
                }
        }

        public static double getStotalTime() {
                return stotalTime;
        }

        public static void setStotalTime(double stotalTime) {
                if (CasperProfiler.stotalTime == 0
                                || stotalTime < CasperProfiler.stotalTime) {
                        CasperProfiler.stotalTime = stotalTime;
                }
        }

        public static double getSreduceTime() {
                return sreduceTime;
        }

        public static void setSreduceTime(double sreduceTime) {
                if (CasperProfiler.sreduceTime == 0
                                || sreduceTime < CasperProfiler.sreduceTime) {
                        CasperProfiler.sreduceTime = sreduceTime;
                }
        }

        public static double getSqueryTime() {
                return squeryTime;
        }

        public static void setSqueryTime(double squeryTime) {
                if (CasperProfiler.squeryTime == 0
                                || squeryTime < CasperProfiler.squeryTime) {
                        CasperProfiler.squeryTime = squeryTime;
                }
        }

        public static double getSfilterTime() {
                return sfilterTime;
        }

        public static void setSfilterTime(double sfilterTime) {
                if (CasperProfiler.sfilterTime == 0
                                || sfilterTime < CasperProfiler.sfilterTime) {
                        CasperProfiler.sfilterTime = sfilterTime;
                }
        }
        
        public static int getSobjectCount3() {
                return sobjectCount*3;
        }
        
        public static int getSobjectCount2() {
                return sobjectCount*2;
        }
        
        public static int getSobjectCount() {
                return sobjectCount;
        }

        public static void setSobjectCount(int sobjectCount) {
                if (CasperProfiler.sobjectCount == 0
                                || sobjectCount < CasperProfiler.sobjectCount) {
                        CasperProfiler.sobjectCount = sobjectCount;
                }
        }

        public static int getN() {
                return n;
        }
        
        public static int getN3() {
                return n/3 == 0 ? 1 : n/3;
        }
}